﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShuticsEntities;
using System.ComponentModel;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Interop.Excel;

namespace ShuticsBiz
{
    public static class ControlEvaluacion
    {
        private static int seed = DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second + DateTime.Now.Millisecond;
        private static Random rand = new Random(seed);

        public static Dictionary<Candidato, string> GenerarClaves(BindingList<Candidato> candidatos)
        {
            Dictionary<Candidato, string> dicCandidatoClave = new Dictionary<Candidato, string>();

            foreach (Candidato c in candidatos)
            {
                string clave = CrearClave(8);
                dicCandidatoClave.Add(c, clave);
            }

            return dicCandidatoClave;
        }

        private static string CrearClave(int longitud)
        {
            string caracteresPermitidos = "ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
            char[] clave = new char[longitud];            

            for (int i = 0; i < longitud; i++)
            {
                clave[i] = caracteresPermitidos[rand.Next(0, caracteresPermitidos.Length)];
            }
            seed++;

            return new string(clave);
        }

        public static bool GenerarEvaluacion(Puesto puesto, Dictionary<Candidato, string> dicCandidatoClave)
        {
            try
            {
                List<Configuracion> config = Model.context.Configuracion.ToList();                

                Evaluacion eval = new Evaluacion();
                eval.Instrucciones = config.Single(c => c.Nombre == "instrucciones").Valor;
                eval.PreguntasPorBloque = int.Parse(config.Single(c => c.Nombre == "preguntasPorBloque").Valor);
                eval.TiempoMaximoFinalizacion = int.Parse(config.Single(c => c.Nombre == "tiempoMaximoFinalizacion").Valor);
                eval.TiempoMaximoIngreso = int.Parse(config.Single(c => c.Nombre == "tiempoMaximoIngreso").Valor);
                eval.CantidadCandidatosEvaluados = dicCandidatoClave.Count;
                eval.Fecha = DateTime.Now;
                puesto.Evaluaciones.Add(eval);

                Model.context.Evaluacion.AddObject(eval);

                foreach (KeyValuePair<Candidato, string> candidato in dicCandidatoClave)
                {
                    List<CuestionarioPregunta> preguntasCandidato = new List<CuestionarioPregunta>();

                    Cuestionario cuest = new Cuestionario();
                    cuest.Candidato = candidato.Key;
                    cuest.Clave = candidato.Value;
                    cuest.BloqueActivo = 1;
                    cuest.Estado = Model.context.Estado.Single(c => c.ID == (int)ControlCuestionario.Estados.Activo);
                    cuest.Evaluacion = eval;                    

                    foreach (PuestoCompetencia ponderacion in puesto.Ponderaciones)
                    {
                        if(!ponderacion.CompetenciaReference.IsLoaded)
                        {
                            ponderacion.CompetenciaReference.Load();
                        }

                        //Si la competencia esta eliminada, no la evaluamos
                        if (!ponderacion.Competencia.Eliminado)
                        {
                            if (!ponderacion.Competencia.Factores.IsLoaded)
                            {
                                ponderacion.Competencia.Factores.Load();
                            }

                            CuestionarioCompetencia cc = new CuestionarioCompetencia();
                            cc.Codigo = ponderacion.Competencia.Codigo;
                            cc.Nombre = ponderacion.Competencia.Nombre;
                            cc.Ponderacion = ponderacion.Ponderacion;

                            foreach (Factor factor in ponderacion.Competencia.Factores)
                            {
                                //Si el factor esta eliminado o no es evaluable, no lo tenemos en cuenta
                                if (!factor.Eliminado && ControlFactor.EsEvaluable(factor))
                                {

                                    if (!factor.Preguntas.IsLoaded)
                                    {
                                        factor.Preguntas.Load();
                                    }

                                    CuestionarioFactor cuestionarioFactor = new CuestionarioFactor();
                                    cuestionarioFactor.Codigo = factor.Codigo;
                                    cuestionarioFactor.Nombre = factor.Nombre;

                                    List<Pregunta> pregAleatorias = ObtenerPreguntasAleatorias(factor, 5);

                                    foreach (Pregunta pregunta in pregAleatorias)
                                    {
                                        if (!pregunta.Puntajes.IsLoaded)
                                        {
                                            pregunta.Puntajes.Load();
                                        }
                                        if (!pregunta.OpcionReference.IsLoaded)
                                        {
                                            pregunta.OpcionReference.Load();
                                        }

                                        CuestionarioPregunta cuestionarioPregunta = new CuestionarioPregunta();
                                        cuestionarioPregunta.Pregunta = pregunta.Pregunta1;

                                        foreach (PreguntaItem item in pregunta.Puntajes)
                                        {
                                            if (!item.OpcionItemReference.IsLoaded)
                                            {
                                                item.OpcionItemReference.Load();
                                            }
                                            CuestionarioItem cuestionarioItem = new CuestionarioItem();
                                            cuestionarioItem.Descripcion = item.OpcionItem.Descripcion;
                                            cuestionarioItem.Orden = item.OpcionItem.Orden;
                                            cuestionarioItem.Puntaje = item.Puntaje;
                                            cuestionarioItem.Seleccionado = false;

                                            cuestionarioPregunta.Items.Add(cuestionarioItem);
                                        }

                                        cuest.Preguntas.Add(cuestionarioPregunta);
                                        cuestionarioFactor.Preguntas.Add(cuestionarioPregunta);
                                        preguntasCandidato.Add(cuestionarioPregunta);
                                    }
                                    cc.Factores.Add(cuestionarioFactor);
                                }
                            
                            }
                            cuest.Competencias.Add(cc);
                        }
                    }

                    GenerarOrden(preguntasCandidato);
                    Model.context.Cuestionario.AddObject(cuest);
                }
                Model.context.SaveChanges();
            }
            catch(Exception)
            {
                return false;
            }

            return true;
        }

        private static void GenerarOrden(List<CuestionarioPregunta> preguntasCandidato)
        {
            preguntasCandidato = preguntasCandidato.OrderBy(a => Guid.NewGuid()).ToList();
            for (int i=0; i < preguntasCandidato.Count; i++)
            {
                preguntasCandidato[i].Orden = i;
            }
        }

        private static List<Pregunta> ObtenerPreguntasAleatorias(Factor factor, int cantidadPreguntasXFactor)
        {
            List<Pregunta> aleatorias = new List<Pregunta>();
            //Tomamos como origen la lista de preguntas no eliminadas del factor
            List<Pregunta> pregFactor = factor.Preguntas.Where(c=> !c.Eliminado).ToList();

            for (int i = 0; i < cantidadPreguntasXFactor; i++)
            {
                Pregunta pregSeleccionada = pregFactor[rand.Next(0, pregFactor.Count)];
                aleatorias.Add(pregSeleccionada);
                pregFactor.Remove(pregSeleccionada);
            }
            seed++;

            return aleatorias;
        }

        public static bool GenerarArchivo(Dictionary<Candidato, string> claves, Puesto p, string path)
        {
            try
            {
                object misValue = System.Reflection.Missing.Value;

                Excel.Application xlApp = new Excel.Application();
                Workbook xlWorkBook = xlApp.Workbooks.Add(XlSheetType.xlWorksheet);
                Worksheet xlWorkSheet = (Worksheet)xlApp.ActiveSheet;

                int i = 1;
                xlWorkSheet.Cells[i, 1] = "Apellido";
                xlWorkSheet.Cells[i, 2] = "Nombre";
                xlWorkSheet.Cells[i, 3] = "Tipo de Documento";
                xlWorkSheet.Cells[i, 4] = "Nro. Documento";
                xlWorkSheet.Cells[i, 5] = "Clave";

                foreach(KeyValuePair<Candidato,string> candidatoClave in claves)
                {
                    xlWorkSheet.Cells[i + 1, 1] = candidatoClave.Key.Apellido;
                    xlWorkSheet.Cells[i + 1, 2] = candidatoClave.Key.Nombre;
                    xlWorkSheet.Cells[i + 1, 3] = candidatoClave.Key.TipoDoc.Nombre;
                    xlWorkSheet.Cells[i + 1, 4] = candidatoClave.Key.NroDocumento;
                    xlWorkSheet.Cells[i + 1, 5] = candidatoClave.Value;
                    i++;
                }

                string filename = path + "\\" + DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" 
                                  + DateTime.Now.Hour + "-" + DateTime.Now.Minute + "-" + p.Nombre + ".xls";
                xlWorkBook.SaveAs(filename, XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
                xlWorkBook.Close(true, misValue, misValue);
                xlApp.Quit();

                releaseObject(xlWorkSheet);
                releaseObject(xlWorkBook);
                releaseObject(xlApp);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private static void releaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                obj = null;
            }
            catch (Exception)
            {
                obj = null;                
            }
            finally
            {
                GC.Collect();
            }
        }

        public static List<int> ObtenerInformacionDeEvaluacion(Evaluacion evaluacion)
        {
            List<int> info = new List<int>();
            int id = evaluacion.ID;
            
            info.Add(Model.context.Cuestionario.Where(c => (((int)c.Evaluacion.ID == id) && (c.Estado.Nombre.Equals("Completo")))).ToList().Count);
            info.Add(Model.context.Cuestionario.Where(c => (((int)c.Evaluacion.ID == id) && (c.Estado.Nombre.Equals("Incompleto")))).ToList().Count);
            info.Add(Model.context.Cuestionario.Where(c => (((int)c.Evaluacion.ID == id) && (c.Estado.Nombre.Equals("Sin contestar")))).ToList().Count);

            return info;
        }
    }
}
